﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;
using System.Web.Script.Serialization;
using System.Diagnostics;

namespace ManiaHome
{
	/// <summary>
	/// ManiaHome C# client
	/// </summary>
	public class ManiaHomeClient
	{
		#region Fields

		/// <summary>
		/// The _sender
		/// </summary>
		private string _sender;

		/// <summary>
		/// The _apiUsername
		/// </summary>
		private string _apiUsername;

		/// <summary>
		/// The _apiPassword
		/// </summary>
		private string _apiPassword;

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instace of the <see cref="ManiaHome"/> class
		/// </summary>
		/// <param name="sender">Manialink or website</param>
		/// <param name="username">API username</param>
		/// <param name="password">API password</param>
		public ManiaHomeClient(string sender, string username, string password)
		{
			this._sender = sender;
			this._apiUsername = username;
			this._apiPassword = password;
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Sends a notification to everyone who bookmarked the manialink
		/// </summary>
		/// <param name="message"></param>
		/// <param name="link"></param>
		public void SendNotificationFromManialink(string message, string link = null, string style = null, string subStyle = null)
		{
			Dictionary<string, object> data = new Dictionary<string, object>();
			data.Add("senderName", this._sender);
			data.Add("message", message);
			data.Add("receiverName", null);
			data.Add("link", link);
			data.Add("iconStyle", style);
			data.Add("iconSubStyle", subStyle);
			data.Add("type", 0);

			// POST
			this.Post("/maniahome/notification/", data);
		}

		/// <summary>
		/// Sends a public notification to a player
		/// </summary>
		/// <param name="playerLogin">Player login</param>
		/// <param name="message">Message to send</param>
		public void SendPublicNotification(string playerLogin, string message, string link = null, string style = null, string subStyle = null)
		{
			Dictionary<string, object> data = new Dictionary<string, object>();
			data.Add("senderName", this._sender);
			data.Add("message", message);
			data.Add("link", link);
			data.Add("iconStyle", style);
			data.Add("iconSubStyle", subStyle);
			data.Add("type", 0);

			string resourceLocation = String.Format("/maniahome/notification/{0}/", playerLogin);

			// POST
			this.Post(resourceLocation, data);
		}

		/// <summary>
		/// Sends a private notifcation to a player
		/// </summary>
		/// <param name="playerLogin">Player login</param>
		/// <param name="message">Message to send</param>
		public void SendPrivateNotifaction(string playerLogin, string message, string link = null)
		{
			Dictionary<string, object> data = new Dictionary<string, object>();
			data.Add("senderName", this._sender);
			data.Add("message", message);
			data.Add("link", link);

			string resourceLocation = String.Format("/maniahome/notification/{0}/private", playerLogin);

			// POST
			this.Post(resourceLocation, data);
		}

		#endregion

		#region Private Methods

		/// <summary>
		/// Performs the initial request to the API
		/// </summary>
		/// <param name="resource">Formatted resource URL</param>
		/// <param name="data">Dictionary with the data</param>
		private void Post(string resource, Dictionary<string, object> data)
		{
			// Accept all certificates, delegate the callback to true
			// Nadeo's certificates are self-signed
			ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(delegate { return true; });
			
			string authInfo = this._apiUsername + ":" + this._apiPassword;

			HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.maniastudio.com/" + resource);
			request.Accept = "application/json";
			request.ContentType = "application/json";
			request.Method = "POST";
			request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(authInfo)));
			request.Timeout = 10000; // 10 seconds
			request.UserAgent = "ManiaHome ASP.NET Library"; // TODO: ManiaHome ASP.NET (CS) Library

			JavaScriptSerializer serializer = new JavaScriptSerializer();
			string jsonData = serializer.Serialize(data); // Serialize data

			byte[] byteArray = Encoding.UTF8.GetBytes(jsonData); // Get bytes

			request.ContentLength = byteArray.Length; // Set content length

			try
			{
				using (Stream stream = request.GetRequestStream())
				{
					// Write data to stream
					stream.Write(byteArray, 0, byteArray.Length);
				}

				string serverResponse = String.Empty;

				using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
				{
					using (Stream stream = response.GetResponseStream())
					{
						using (StreamReader reader = new StreamReader(stream))
						{
							// TODO: do something or do nothing
							serverResponse = reader.ReadToEnd(); // Get response

#if DEBUG
							// If successful the only response should be "null"
							Debug.WriteLine(serverResponse);
#endif
						}
					}
				}
			}

			catch (WebException ex)
			{
				using (WebResponse response = ex.Response)
				{
					HttpWebResponse httpResponse = (HttpWebResponse)response;

					using (Stream stream = httpResponse.GetResponseStream())
					{
						StreamReader reader = new StreamReader(stream);
#if DEBUG
						// Unsuccessful, write the response message
						Debug.WriteLine(reader.ReadToEnd());
#endif
					}
				}
			}
		}

		#endregion
	}
}